﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using LevenBlog.Core.Data;
using LevenBlog.Core.Entities;
using LevenBlog.Core.Utils;
using LevenBlog.Core.Service;

namespace LevenBlog.Core.User
{
    public class UserMembership : IMembership
    {
        public static string cookieName = WebConfig.PrefixKey + "LevenBlogUserCookie";

        public IDbProvider Provider { get; set; }

        public lb_user User { get; protected set; }

        public IAuthority Authority { get; protected set; }

        public string CookieString { get; protected set; }

        protected virtual string CookieName
        {
            get { return cookieName; }
        }

        public UserMembership()
        {
            Provider = null;
            User = new lb_user();
            Authority = new Authority();
            CookieString = string.Empty;
        }

        public UserMembership(IDbProvider provider)
            : this()
        {
            Provider = provider;
            User = BlogUser.Default(Provider);
            Authority = new Authority();
            CookieString = string.Empty;
        }

        public virtual void Read()
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(CookieName);
            if (cookie == null)
            {
                User = BlogUser.Default(Provider);
                User.usertype = UserType.GetDefault(Provider);
            }
            else
            {
                CookieString = cookie.Value;
                try {
                    User = SecurityCookie.DecryptFromBase64(cookie.Value);
                } catch {
                    throw new Exception("解密Cookie失败.");
                }
                User.usertype = UserType.Get(Provider, User.typeid);
                if (User.usertype == null)
                    throw new Exception("无法获取用户的权限信息.");
            }
            try
            {
                Authority.Fill(User.usertype.competence);
            }
            catch (Exception e)
            {
                throw new Exception("无法将数据库中的权限数据转换为数据实体", e);
            }
        }

        /// <summary>
        /// 如果需要获取User的详细信息,请先执行该方法,否则会错误
        /// </summary>
        public void LoadFull()
        {
            User = BlogUser.Get(Provider, User.id);
        }

        public virtual void Write(DateTime expressTime)
        {
            HttpCookie cookie = new HttpCookie(CookieName);
            lb_user user = new lb_user();
            user.id = User.id;
            user.name = User.name;
            user.password = User.password;
            user.postnum = User.postnum;
            user.typeid = User.typeid;
            cookie.Value = SecurityCookie.EncryptToBase64(user);
            if (expressTime != DateTime.MaxValue && expressTime != DateTime.MinValue)
            {
                cookie.Expires = expressTime;
            }
            HttpContext.Current.Response.Cookies.Add(cookie);
        }

        public virtual void Write()
        {
            Write(DateTime.MinValue);
        }

        public bool Login(string username, string password, DateTime loginTime)
        {
            lb_user user = BlogUser.Get(Provider, username);
            if (user == null)
                return false;
            else
            {
                if (user.password == password.ToMD5())
                {
                    User = user;
                    if (User.userinfo == null)
                    {
                        throw new ArgumentNullException("User.userinfo");
                    }
                    User.userinfo.lastlogintime = DateTime.Now;
                    User.userinfo.lastloginip = Fetch.UserIp;
                    BlogUser.Update(Provider, User);
                    User.usertype = UserType.Get(Provider, user.typeid);
                    Write(loginTime);
                    return true;
                }
                return false;
            }
        }

        public bool Login(string username, string password)
        {
            return Login(username, password, DateTime.MinValue);
        }

        public void Logout()
        {
            User = BlogUser.Default(Provider);
            Write();
        }

        public bool CheckUser(string username)
        {
            lb_user user = BlogUser.Get(Provider, username.SqlEncode());
            if (user == null)
                return false;
            else
                return true;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}
